package wn.lizzy.liums.config.datasource;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * 从数据源配置
 * RepositorySecondaryConfig.java
 * @author cuilijian  2017年3月20日--下午4:59:35
 *
 * 1) 引入 LazyConnectionDataSourceProxy
 * 只有 dataSource 获取到Connection之后，在执行 Java.sql.Connection#prepareStatement(java.lang.String) 时候，
 * Spring 才会主动去数据库链接池中获取 Connection ，这样做的好处就是提高数据库链接的使用率和效率； 
	LazyConnectionDataSourceProxy 经常会被用在一些分库分表、多数据源事务的应用当中； 
    多数据源的事务管理解决方案，很多采用了同时开启所有数据源事务、同时提交的策略，例如：阿里的 cobar 解决方案等； 
   使用了 LazyConnectionDataSourceProxy 则在执行 Connection#prepareStatement 之前，spring 是不会向数据库连接池获取数据库链接的
 */
@Configuration  
@EnableTransactionManagement  
@EnableJpaRepositories(  
        entityManagerFactoryRef="entityManagerFactorySecondary",  
        transactionManagerRef="transactionManagerSecondary",  
        basePackages= { "wn.lizzy.liums.front.huge" })  
	public class RepositorySecondaryConfig {
		@Resource
		private Environment env;
	  
	    @Autowired @Qualifier("SecondaryDataSource")  
	    private DataSource secondaryDataSource;  
	  
	    @Bean(name = "entityManagerSecondary")  
	    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {  
	        return entityManagerFactorySecondary(builder).getObject().createEntityManager();  
	    }  
	  
	    @Bean(name = "entityManagerFactorySecondary")  
	    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {  
	        return builder
	                .dataSource(new LazyConnectionDataSourceProxy(secondaryDataSource))  
	                .properties(getHibernateProperties())  
	                .packages(new String[] {"wn.lizzy.liums.front.huge.entity"})  
	                .persistenceUnit("secondaryPersistenceUnit")  
	                .build();  
	    }  
	  
	    private Map<String, String> getHibernateProperties() {  
	    	Map<String, String> propertiesMap = new HashMap<String, String>();
	    	propertiesMap.put("hibernate.dialect", env.getProperty("spring.read.hibernate.dialect"));
//			propertiesMap.put("hibernate.default_catalog", env.getProperty("hibernate.catalog"));
			propertiesMap.put("hibernate.connection.release_mode", "auto");
			propertiesMap.put("hibernate.bytecode.use_refection_optimizer", "true");
			propertiesMap.put("hibernate.bytecode.provider", "cglib");
			propertiesMap.put("hibernate.current_session_context_class", "thread");

			propertiesMap.put("hibernate.max_fetch_depth", "1");
			propertiesMap.put("hibernate.default_batch_fetch_size", "100");
			propertiesMap.put("hibernate.jdbc.fetch.size", "30");
			propertiesMap.put("hibernate.jdbc.batch_size", "50");

			// 二级缓存
			propertiesMap.put("hibernate.cache.use_second_level_cache",env.getProperty("spring.read.hibernate.use_second_level_cache"));
			// 查询缓存
			propertiesMap.put("hibernate.cache.use_query_cache", env.getProperty("spring.read.hibernate.use_query_cache"));
//			// 缓存实现
//			System.out.println("二级缓存" + org.hibernate.cache.ehcache.EhCacheRegionFactory.class.getName());
//			propertiesMap.put("hibernate.cache.region.factory_class", org.hibernate.cache.ehcache.EhCacheRegionFactory.class.getName());
//			// 缓存配置
			propertiesMap.put("net.sf.ehcache.configurationResourceName", "ehcache.xml");
			
			// 是否显示 SQL
			propertiesMap.put("hibernate.show_sql", env.getProperty("spring.read.hibernate.show-sql"));
			// 是否格式化 SQL
			propertiesMap.put("hibernate.format_sql", env.getProperty("spring.read.hibernate.format_sql"));
			
	        return propertiesMap;  
	    }  
	    
	    /**
	     * 事务管理器
	     * @param builder
	     * @return
	     */
	    @Bean(name = "transactionManagerSecondary")  
	    PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {  
	        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());  
	    }  
	}
